package com.sunbim.rsrv.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunbim.rsrv.common.exception.RequestException;
import com.sunbim.rsrv.mapper.*;
import com.sunbim.rsrv.params.relics.RiskUpdateParams;
import com.sunbim.rsrv.pojo.*;
import com.sunbim.rsrv.service.*;
import com.sunbim.rsrv.util.common.SortUtil;
import com.sunbim.rsrv.vo.relics.RelicsWithRiskVo;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yuhui
 * @since 2021-12-30
 */
@Service
public class RelicsServiceImpl extends ServiceImpl<RelicsMapper, Relics> implements RelicsService {

    @Autowired
    RelicsMapper relicsMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    StorageService storageService;
    @Autowired
    StorageMapper storageMapper;
    @Autowired
    RiskAroundMapper riskAroundMapper;
    @Autowired
    RiskBodyMapper riskBodyMapper;
    @Autowired
    RiskStatueMapper riskStatueMapper;
    @Autowired
    RiskRockyMapper riskRockyMapper;
    @Autowired
    RiskManageMapper riskManageMapper;
//    @Autowired
//    RiskStructMapper riskStructMapper;


    @Autowired
    RiskBodyService riskBodyService;
    @Autowired
    RiskStatueService riskStatueService;
    @Autowired
    RiskRockyService riskRockyService;
    @Autowired
    RiskAroundService riskAroundService;
    @Autowired
    RiskStructService riskStructService;
    @Autowired
    RiskManageService riskManageService;

    private final List<String> relicasGrade = Arrays.asList("国保单位", "省保单位", "市保单位", "区/县级文保单位", "其它");
    private final List<String> relicsGrandBatch = Arrays.asList("第一批", "第二批", "第三批", "第四批", "第五批", "第六批", "第七批", "第八批", "第九批", "第十批", "第十一批");
    private final List<String> era = Arrays.asList("夏", "商", "西周", "东周", "春秋", "战国", "秦", "西汉", "东汉", "三国", "西晋", "东晋", "南北朝", "隋", "唐", "五代十国", "辽", "北宋", "金", "南宋", "元", "明", "清", "民国", "近代");


    @Override
    public List<Map<String, Object>> getAll() {
        return relicsMapper.selectMaps(null);
    }

    @Override
    public List<Map<String, Object>> getAllByUserIdWithDanger(Integer userId) {
        // 获取带有风险排名、风险得分的文物数据列表
        List<Map<String, Object>> data = relicsMapper.getAllWithDangerInfo(userId);
        Set<Integer> bodyScore = new LinkedHashSet<>();
        Set<Integer> cateGoryScore = new LinkedHashSet<>();
        data.stream().forEach(map -> {
            if (Convert.toInt(map.get("body_score"), 0) + Convert.toInt(map.get("category_score"), 0)
                    + Convert.toInt(map.get("around_score"), 0) + Convert.toInt(map.get("manage_score"), 0) != 0) {
                bodyScore.add(Convert.toInt(map.get("body_score"), 0));
                cateGoryScore.add(Convert.toInt(map.get("category_score"), 0));
            }
        });
        // 分数为0也参与排序
        List<Integer> sortedBodyScore = bodyScore.stream().sorted().collect(Collectors.toList());
        List<Integer> sortedCategoryScore = cateGoryScore.stream().sorted().collect(Collectors.toList());
        for (Map<String, Object> item : data) {
            Integer body_score = Convert.toInt(item.get("body_score"), 0);
            Integer category_score = Convert.toInt(item.get("category_score"), 0);
            Integer around_score = Convert.toInt(item.get("around_score"), 0);
            Integer manage_score = Convert.toInt(item.get("manage_score"), 0);
            if (body_score + category_score + around_score + manage_score == 0) {
                item.put("danger_level", 0);
            } else {
                int max = NumberUtil.max(RiskBodyServiceImpl.getLevel(body_score, sortedBodyScore),
                        RiskBodyServiceImpl.getLevel(category_score, sortedCategoryScore),
                        RiskAroundServiceImpl.getLevel(around_score),
                        RiskManageServiceImpl.getLevel(manage_score));
                item.put("danger_level", max);
            }
            item.remove("body_score");
            item.remove("category_score");
            item.remove("around_score");
            item.remove("manage_score");
        }
        List<Map<String, Object>> result = data.stream().sorted(Comparator.comparingInt(o -> Convert.toInt(o.get("danger_level")))).collect(Collectors.toList());

        return result;
    }

    @SneakyThrows
    @Transactional
    @Override
    public void insertOne(Relics relics, MultipartFile file) {
        // 用户id不存在
        Integer userId = relics.getUserId();
        boolean isExist = userMapper.idExist(userId);
        if (!isExist) throw new RequestException("该用户id不存在");

        // 文物名称已存在
        boolean isNameExist = relicsMapper.nameExist(userId, relics.getRelicsName());
        if (isNameExist) throw new RequestException("文物名称: " + relics.getRelicsName() + " 已存在");

        relicsMapper.insert(relics);
        // 插入成功后, 同时插入对应的风险数据, 指数均为0
        RiskAround riskAround = new RiskAround();
        RiskBody riskBody = new RiskBody();
        RiskManage riskManage = new RiskManage();
        RiskStruct riskStruct = new RiskStruct();
        Integer relicsId = relics.getId();
        riskAround.setRelicsId(relicsId);
        riskAround.setUserId(userId);
        riskBody.setRelicsId(relicsId);
        riskBody.setUserId(userId);
        riskManage.setRelicsId(relicsId);
        riskManage.setUserId(userId);
        riskStruct.setRelicsId(relicsId);
        riskStruct.setUserId(userId);


        riskAroundMapper.insert(riskAround);
        riskBodyMapper.insert(riskBody);

        riskManageMapper.insert(riskManage);
        storageService.upload(null, null, relicsId, "icon", "", file);
    }

    @Override
    public void updateByRelicsId(Relics relics) {
        boolean isNameExist = relicsMapper.nameExistExcludOwn(relics.getId(), relics.getUserId(), relics.getRelicsName());
        if (isNameExist) throw new RequestException("文物名称: " + relics.getRelicsName() + " 已存在");

        boolean isIdExist = relicsMapper.relicsExist(relics.getId(), relics.getUserId());
        if (!isIdExist) throw new RequestException("用户 " + relics.getUserId() + ",文物id: " + relics.getId() + " 不存在");
        relicsMapper.updateById(relics);
    }

    @Transactional
    @Override
    public void deleteRelics(List<Integer> ids) {
        relicsMapper.deleteBatchIds(ids);

//        QueryWrapper<RiskStruct> structWrapper = new QueryWrapper<>();
//        structWrapper.in("relics_id", ids);
//        riskStructMapper.delete(structWrapper);

        QueryWrapper<RiskAround> aroundWrapper = new QueryWrapper<>();
        aroundWrapper.in("relics_id", ids);
        riskAroundMapper.delete(aroundWrapper);

        QueryWrapper<RiskBody> bodyWrapper = new QueryWrapper<>();
        bodyWrapper.in("relics_id", ids);
        riskBodyMapper.delete(bodyWrapper);

        QueryWrapper<RiskStatue> statueWrapper = new QueryWrapper<>();
        statueWrapper.in("relics_id", ids);
        riskStatueMapper.delete(statueWrapper);

        QueryWrapper<RiskRocky> rockyWrapper = new QueryWrapper<>();
        rockyWrapper.in("relics_id", ids);
        riskRockyMapper.delete(rockyWrapper);

        QueryWrapper<RiskManage> manageWrapper = new QueryWrapper<>();
        manageWrapper.in("relics_id", ids);
        riskManageMapper.delete(manageWrapper);

        QueryWrapper<Storage> storageWrapper = new QueryWrapper<>();
        storageWrapper.in("relics_id", ids);
        storageMapper.delete(storageWrapper);

    }

    @Override
    public Relics selectOne(int relicsId) {
        return relicsMapper.selectById(relicsId);
    }

    @Override
    public Relics selectOne(int loginIdAsInt, int relicsId) {
        QueryWrapper<Relics> relicsQueryWrapper = new QueryWrapper<>();

        // select * from relics where id= relicsId AND user_id = 当前登录用户的id
        relicsQueryWrapper.eq("id", relicsId);
        relicsQueryWrapper.eq("user_id", loginIdAsInt);
        return relicsMapper.selectOne(relicsQueryWrapper);
    }

    @Override
    public List<Map<String, Object>> selectGradeByUserId(Integer userId) {
        return relicsMapper.selectGradeByUserId(userId);
    }

    @Override
    public List<Map<String, Object>> selectRegionByUserId(Integer userId) {
        return relicsMapper.selectRegionByUserId(userId);
    }

    @Override
    public List<Map<String, Object>> selectTypeByUserId(Integer userId) {
        return relicsMapper.selectTypeByUserId(userId);
    }

    @Override
    public List<Map<String, Object>> selectByUserIdWithCondition(Integer userId, String condition) {
        User user = userMapper.selectById(userId);
        if (ObjectUtil.isNull(user)) throw new RequestException("该用户id不存在");

        switch (condition) {
            case "region":
                return relicsMapper.selectRegionByUserId(userId);
            case "type":
                return relicsMapper.selectTypeByUserId(userId);
            case "grade":
                List<Map<String, Object>> mapList = relicsMapper.selectGradeByUserId(userId);
                Map<String, List<String>> orderMap = new LinkedHashMap<>();
                orderMap.put("title", relicasGrade);
                List<Map<String, Object>> sorted = SortUtil.sorted(mapList, orderMap);
                return sorted;
            case "level":
                List<Map<String, Object>> allByUserIdWithDanger = getAllByUserIdWithDanger(userId);
                Map<Integer, List<Map<String, Object>>> danger_levelMap = allByUserIdWithDanger.stream().collect(Collectors.groupingBy(a -> (Integer) a.get("danger_level")));
                List<Map<String, Object>> result = new ArrayList<>();
                Iterator<Map.Entry<Integer, List<Map<String, Object>>>> iterator = danger_levelMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<Integer, List<Map<String, Object>>> next = iterator.next();
                    Integer levelInt = next.getKey();
                    Map<String,Object> map = new HashMap<>();
                    map.put("title",0==levelInt?"未参评":1==levelInt?"一级":2==levelInt?"二级":3==levelInt?"三级":"四级");
                    map.put("item",next.getValue());
                    result.add(map);
                }
                return result;
            default:
                throw new RequestException("条件类型错误,需要是'region'、'type'、'grade'其中的一个");
        }
    }

    @Override
    public List<Relics> getAllByUserId(int userId) {
        QueryWrapper<Relics> relicsQueryWrapper = new QueryWrapper<>();
        relicsQueryWrapper.eq("user_id", userId);
        List<Relics> relics = relicsMapper.selectList(relicsQueryWrapper);

        // 排序
        Map<String, List<String>> orderMap = new LinkedHashMap<>();
        orderMap.put("relicsGrade", relicasGrade);
        orderMap.put("relicsGrandBatch", relicsGrandBatch);
        orderMap.put("relicsAge", era);

        List<Relics> sorted = SortUtil.sorted(relics, orderMap);
        return sorted;
    }

    @Override
    public RelicsWithRiskVo selectRiskOne(Integer userId, Integer relicsId) {
        QueryWrapper<Relics> relicsQueryWrapper = new QueryWrapper<>();
        relicsQueryWrapper.select("id", "relics_name", "relics_advice").eq("user_id", userId).eq("id", relicsId);
        Relics relics = relicsMapper.selectOne(relicsQueryWrapper);
        if (ObjectUtil.isNull(relics)) throw new RequestException("用户: " + userId + ",文物id: " + relicsId + " 不存在");
        RiskAround aroundMap = riskAroundService.selectByRelicsId(userId, relicsId);
//        RiskStruct structMap = riskStructService.selectByRelicsId(userId, relicsId);
        RiskBody bodyMap = riskBodyService.selectByRelicsId(userId, relicsId);
//        RiskStatue statueMap = riskStatueService.selectByRelicsId(userId, relicsId);
//        RiskRocky rockyMap = riskRockyService.selectByRelicsId(userId, relicsId);
        RiskManage manageMap = riskManageService.selectByRelicsId(userId, relicsId);

        RelicsWithRiskVo vo = new RelicsWithRiskVo();
        vo.setId(relics.getId());
        vo.setRelicsName(relics.getRelicsName());
        vo.setRelicsAdvice(relics.getRelicsAdvice());
        vo.setRiskAround(aroundMap);
        vo.setRiskBody(bodyMap);
        vo.setRiskManage(manageMap);
//        vo.setRiskStatue(statueMap);
//        vo.setRiskRocky(rockyMap);
        return vo;
    }

    @Transactional
    @Override
    public void updateRisk(RiskUpdateParams params) {
        Integer id = params.getId();
        String relicsAdvice = params.getRelicsAdvice();
        Relics relics = relicsMapper.selectById(id);
        relics.setRelicsAdvice(relicsAdvice);
        relicsMapper.updateById(relics);

        if (ObjectUtil.isNotNull(params.getRiskAround())) riskAroundService.updateByRiskId(params.getRiskAround());
        if (ObjectUtil.isNotNull(params.getRisk_body())) riskBodyService.updateByRiskId(params.getRisk_body());
//        if (ObjectUtil.isNotNull(params.getRisk_statue())) riskStatueService.updateByRiskId(params.getRisk_statue());
//        if (ObjectUtil.isNotNull(params.getRisk_rocky())) riskRockyService.updateByRiskId(params.getRisk_rocky());
        if (ObjectUtil.isNotNull(params.getRiskManage())) riskManageService.updateByRiskId(params.getRiskManage());
//        if (ObjectUtil.isNotNull(params.getRiskStruct())) riskStructService.updateByRiskId(params.getRiskStruct());
    }

    // yuhui 2022-2-23 文物模糊查找
    @Override
    public List<Map<String, Object>> searchByRelicsName() {
        QueryWrapper<Relics> wrapper = new QueryWrapper<>();
//        wrapper.like("relics_name", keyword);
        wrapper.select("id", "user_id", "relics_name", "relics_region", "relics_address", "relics_type", "relics_grade", "relics_abstracts", "relics_age",
                "relics_grand_batch", "relics_way", "relics_code", "relics_pubtime", "relics_pubcode", "relics_ownership", "relics_owner", "relics_manager", "relics_overview",
                "relics_value", "relics_advice", "relics_area", "relics_compose", "relics_protection_scope", "relics_protection_scope_area", "relics_build_controller", "relics_build_controller_area", "relics_body_overview",
                "relics_history", "relics_struct", "relics_struct_desc", "relics_geo", "relics_icon", "create_time", "update_time"
        );
        return relicsMapper.selectMaps(wrapper);
    }


    @Override
    public List<Map<String, Object>> searchByRelicsName(int loginIdAsInt) {

        QueryWrapper<Relics> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", loginIdAsInt);
//        wrapper.like("relics_name", keyword);
        wrapper.select("id", "user_id", "relics_name", "relics_region", "relics_address", "relics_type", "relics_grade", "relics_abstracts", "relics_age",
                "relics_grand_batch", "relics_way", "relics_code", "relics_pubtime", "relics_pubcode", "relics_ownership", "relics_owner", "relics_manager", "relics_overview",
                "relics_value", "relics_advice", "relics_area", "relics_compose", "relics_protection_scope", "relics_protection_scope_area", "relics_build_controller", "relics_build_controller_area", "relics_body_overview",
                "relics_history", "relics_struct", "relics_struct_desc", "relics_geo", "relics_icon", "create_time", "update_time"
        );
        return relicsMapper.selectMaps(wrapper);
    }

    @Override
    public void deleteRelics(int id) {
        boolean isIdExist = relicsMapper.idExist(id);
        if (!isIdExist) throw new RequestException("文物id: " + id + " 不存在");
        relicsMapper.deleteById(id);

//        QueryWrapper<RiskStruct> structWrapper = new QueryWrapper<>();
//        structWrapper.eq("relics_id", id);
//        riskStructMapper.delete(structWrapper);

        QueryWrapper<RiskAround> aroundWrapper = new QueryWrapper<>();
        aroundWrapper.eq("relics_id", id);
        riskAroundMapper.delete(aroundWrapper);

        QueryWrapper<RiskBody> bodyWrapper = new QueryWrapper<>();
        bodyWrapper.eq("relics_id", id);
        riskBodyMapper.delete(bodyWrapper);

        QueryWrapper<RiskStatue> statueWrapper = new QueryWrapper<>();
        statueWrapper.eq("relics_id", id);
        riskStatueMapper.delete(statueWrapper);

        QueryWrapper<RiskRocky> RockyWrapper = new QueryWrapper<>();
        RockyWrapper.eq("relics_id", id);
        riskRockyMapper.delete(RockyWrapper);

        QueryWrapper<RiskManage> manageWrapper = new QueryWrapper<>();
        manageWrapper.eq("relics_id", id);
        riskManageMapper.delete(manageWrapper);

        storageService.deleteAllByRelicsId(id);
    }
}
